package com.shanghe.house.service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shanghe.house.dto.SceneDTO;
import com.shanghe.house.entity.Scene;
import com.shanghe.house.entity.SceneDevice;
import com.shanghe.house.mapper.SceneDeviceMapper;
import com.shanghe.house.mapper.SceneMapper;

/**
 * 场景服务类
 * 提供场景相关的业务逻辑处理，包括场景的CRUD操作和场景激活
 */
@Service
public class SceneService extends ServiceImpl<SceneMapper, Scene> {
    private final SceneDeviceMapper sceneDeviceMapper;
    private final DeviceService deviceService;

    public SceneService(SceneDeviceMapper sceneDeviceMapper, DeviceService deviceService) {
        this.sceneDeviceMapper = sceneDeviceMapper;
        this.deviceService = deviceService;
    }

    public List<Scene> list() {
        List<Scene> scenes = super.list();
        scenes.forEach(scene -> {
            scene.setDevices(sceneDeviceMapper.findBySceneId(scene.getId()));
        });
        return scenes;
    }

    public Scene getById(Long id) {
        Scene scene = super.getById(id);
        if (scene != null) {
            scene.setDevices(sceneDeviceMapper.findBySceneId(id));
        }
        return scene;
    }

    @Transactional
    public Scene create(SceneDTO sceneDTO) {
        Scene scene = new Scene();
        BeanUtils.copyProperties(sceneDTO, scene, "devices");
        save(scene);
        
        saveSceneDevices(scene, sceneDTO);
        return getById(scene.getId());
    }

    @Transactional
    public Scene update(Long id, SceneDTO sceneDTO) {
        Scene scene = getById(id);
        if (scene == null) {
            throw new RuntimeException("场景不存在");
        }
        BeanUtils.copyProperties(sceneDTO, scene, "devices");
        updateById(scene);
        
        // 删除旧的设备关联
        sceneDeviceMapper.delete(new QueryWrapper<SceneDevice>()
                .eq("scene_id", id));
        
        saveSceneDevices(scene, sceneDTO);
        return getById(id);
    }

    private void saveSceneDevices(Scene scene, SceneDTO sceneDTO) {
        if (sceneDTO.getDevices() != null && !sceneDTO.getDevices().isEmpty()) {
            List<SceneDevice> devices = sceneDTO.getDevices().stream()
                    .map(dto -> {
                        SceneDevice device = new SceneDevice();
                        device.setSceneId(scene.getId());
                        device.setDeviceId(dto.getDeviceId());
                        device.setTargetStatus(dto.getTargetStatus());
                        return device;
                    })
                    .collect(Collectors.toList());
            devices.forEach(sceneDeviceMapper::insert);
        }
    }

    @Transactional
    public void delete(Long id) {
        // 先删除关联的设备
        sceneDeviceMapper.delete(new QueryWrapper<SceneDevice>()
                .eq("scene_id", id));
        // 再删除场景
        removeById(id);
    }

    /**
     * 激活场景
     */
    @Transactional
    public void activate(Long id) {
        Scene scene = getById(id);
        if (scene == null) {
            throw new RuntimeException("场景不存在");
        }

        List<SceneDevice> devices = scene.getDevices();
        if (devices == null || devices.isEmpty()) {
            return;
        }

        // 批量更新设备状态
        Map<Long, Boolean> deviceStatuses = devices.stream()
                .collect(Collectors.toMap(
                    SceneDevice::getDeviceId,
                    SceneDevice::getTargetStatus
                ));
        
        deviceService.batchUpdateStatus(deviceStatuses);

        // 更新场景状态
        lambdaUpdate()
                .set(Scene::getStatus, true)
                .eq(Scene::getId, id)
                .update();
    }

    /**
     * 检查场景中的设备是否都存在
     */
    private void validateSceneDevices(List<SceneDevice> devices) {
        if (devices == null || devices.isEmpty()) {
            return;
        }

        List<Long> deviceIds = devices.stream()
                .map(SceneDevice::getDeviceId)
                .collect(Collectors.toList());

        Map<Long, Boolean> existingDevices = deviceService.getDeviceStatuses(deviceIds);
        
        List<Long> notFoundDevices = deviceIds.stream()
                .filter(id -> !existingDevices.containsKey(id))
                .collect(Collectors.toList());

        if (!notFoundDevices.isEmpty()) {
            throw new RuntimeException("以下设备不存在: " + notFoundDevices);
        }
    }

    public Scene findById(Long id) {
        return getById(id);
    }

    public List<Scene> findAll() {
        return list();
    }
}